# include "../include/memoria.h"

/******************************************************************************/

/* NOTA:
 * 
 * Se considera un sistema con un maximo de 8Mb. Para direccionar esta memoria
 * se necesitan dos tablas de paginas. Los primeros 4Mb, es decir, la primer
 * tabla es comun a todos los procesos. La segunda tabla se modifica segun el
 * proceso que este corriendo; habilitando solo las paginas que corresponden
 * al mismo. */

/******************************************************************************/

/* Mapa de direcciones de memoria. */
static int memory[MAX_PAGES];
long address;

/* Memoria para el directorio y las tablas de paginas. */
char memory_block[(3)*0x1000];

/* Directorio y tablas de paginas. */
unsigned long *directory;
unsigned long *page_table;

/* Vector de procesos. */
extern PROCESS procesos[CANT_PROCESS];
extern PROCESS idle;

/******************************************************************************/

/* Funcion que inicia y habilita la paginacion. Tambien realiza un mapeo de la
 * memoria del sistema para manejar la alocacion de bloques de memoria a las
 * distintas tablas de paginas. */

int
init_paging (void)
{
	int i, j;
	unsigned long table_address = ((unsigned long)memory_block & 0xFFFFF000);
	directory = (unsigned long*)(table_address & 0xFFFFF000);	
	table_address = table_address + PAGE_SIZE;

	/* Se inicia la primer direccion de memoria. Luego de terminar esta
	 * funcion, address tiene la primer direcion disponible para alocar. */

	address = 0;

	/* Se inician las paginas de los primeros 8Mb de memoria. Usualmente
	 * CANT_TABLES vale 2 por lo que crean dos tablas de paginas. */

    for (i = 0; i < CANT_TABLES; i++)
	{
        page_table = (unsigned long*)table_address;
		table_address = table_address + PAGE_SIZE;

        for (j = 0; j < MAX_PAGES; j++)
		{
			page_table[j] = address | 3;
            address = address + PAGE_SIZE;
        }

        directory[i] = (unsigned long)page_table;
        directory[i] = directory[i] | 3;
    }

	/* Se inicia el mapa de memoria para los segundos 4Mb destinados a los
	 * stacks de los procesos. */

	address = MAX_PAGES * PAGE_SIZE;

	for ( i = 0; i < MAX_PAGES; i++ )
	{
		page_table[i] = page_table[i] & 0xFFFFFFFE;
		memory[i] = -1;
	}

	/* Se completa el registro cr3 del micro con la direccion anterior. */

	_write_cr3 (directory);

	/* Se habilita la paginacion en el micro. */

	_write_cr0 ( _read_cr0() | 0x80000000 );

	return 0;
}

/******************************************************************************/


